home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / sighash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-06  |  10.6 KB  |  342 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4.  
  5.    Brewster@think.com
  6. */
  7.  
  8. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  9.  
  10.  
  11. /* The memory hashtables for building an index. */
  12. /* -brewster 5/90 */
  13.  
  14. /* main functions:
  15.  *   add_word
  16.  *   finished_add_word
  17.  *   look_up_word
  18.  *
  19.  * The idea is to store up a bunch of words before going to disk.
  20.  * A word entry points to where it will go on disk, and
  21.  * accumulates the entries before doing it.
  22.  *
  23.  * Some of the policy issues in this file are:
  24.  *   How much weight should the first occurance of a word in a document get
  25.  *   over the other occurances.  The first occurance should be worth more
  26.  *   so that words with 3 occurances of "dog" and not "cat"'s should not 
  27.  *   win out over 1 "dog" and 1 "cat" if the question is "Tell me about cats
  28.  *   torture dogs"
  29.  *   The extra weight is 5 at this point.
  30.  *
  31.  */
  32.  
  33. #ifndef lint
  34. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ir/RCS/sighash.c,v 1.4 1994/09/07 13:29:22 pfeifer Exp $";
  35. #endif
  36.  
  37. /* Change log:
  38.  * $Log: sighash.c,v $
  39.  * Revision 1.4  1994/09/07  13:29:22  pfeifer
  40.  * ctype is now included from cdialect.h after inclusion of string.h.
  41.  * Since ctype.h (the local version defines strcmp and friends, inclusion o
  42.  * of string.h after that caused probems
  43.  *
  44.  * Revision 1.3  1994/05/20  12:57:11  pfeifer
  45.  * beta
  46.  *
  47.  * Revision 1.2  1994/03/08  21:06:45  pfeifer
  48.  * Patchlevel 04
  49.  *
  50.  * Revision 1.1  1993/02/16  15:05:35  freewais
  51.  * Initial revision
  52.  *
  53.  * Revision 1.23  92/05/05  13:21:25  shen
  54.  * undo the change make in previous revision 1.22
  55.  * fixed the bug in db->total_word_ccount by checking the last word in t
  56.  * table. If the last word is DICTIONARY_TOTAL_SIZE_WORD, decrement the number
  57.  * of words to add to dictionary file by 1.
  58.  * 
  59.  * Revision 1.22  92/05/05  11:01:54  shen
  60.  * fixed db->total_word_count for incremental update by eliminating adding
  61.  * DICTIONARY_TOTAL_SIZE_WORD to hash table.
  62.  * 
  63.  * Revision 1.21  92/04/29  08:21:15  shen
  64.  * redefine MAX_OCCURANCES to a very big number: 0x10000000.
  65.  * 
  66.  * Revision 1.20  92/03/20  11:04:18  jonathan
  67.  * Added word_postition argument to add word.  See irext.h for explanation.
  68.  * 
  69.  * Revision 1.19  92/03/01  16:11:57  brewster
  70.  * took out analyze_hashtable_distribution
  71.  * 
  72.  * Revision 1.18  92/02/24  19:58:04  jonathan
  73.  * Added code to add the dictionary to the hastable on startup.
  74.  * 
  75.  * Revision 1.17  92/02/12  13:46:18  jonathan
  76.  * Added "$Log" so RCS will put the log message in the header
  77.  * 
  78. */
  79.  
  80. /* To Do:
  81.  *  done: Improve the hashing functions.
  82.  *  done: stop inserting into hash table after max number have been accumulated
  83.  *  done: make flush not flush buffers that are too big.
  84.  */
  85.  
  86. #include "panic.h"
  87. #include "cutil.h"
  88. #include "futil.h"
  89. #include "irfiles.h"
  90. #include "irhash.h"
  91. #include "stoplist.h"
  92. #include "irinv.h"
  93. #include "sigindex.h"
  94.  
  95. #ifdef UNIX
  96. #define PRINT_AS_INDEXING true /* also defined in irtfiles.c and irfiles.c */
  97. #else 
  98. #define PRINT_AS_INDEXING false
  99. #endif
  100.  
  101. #define PROXIMITY /* this turns on writing out of all word occurances */
  102.  
  103.  
  104. /* ---------------------------------------------------- */
  105. static hash_entry* look_up_word _AP((char* word,hashtable*
  106.                      the_word_memory_hashtable));
  107.   
  108. static hash_entry* 
  109. look_up_word(word,the_word_memory_hashtable)
  110. char* word;
  111. hashtable* the_word_memory_hashtable;
  112. {
  113.   hash_entry * answer = get_hash(word, the_word_memory_hashtable);
  114.   
  115.   if(NULL != answer)
  116.     return(answer);
  117.   else{
  118.     hash_entry wrd_entry;
  119.     answer = put_hash(word, the_word_memory_hashtable, &wrd_entry);
  120.     answer->number_of_occurances = 0;
  121.     answer->memory_ptr = NULL;
  122.     answer->memory_size = 0;
  123.     answer->current_memory_ptr = answer->memory_ptr;
  124.     answer->current_doc_id = 0;
  125.     return(answer);
  126.   }
  127. }
  128.  
  129. #ifdef NOTUSED
  130. static unsigned char add_weight _AP((long current_weight,long new_weight));
  131.  
  132. static unsigned char 
  133. add_weight(current_weight,new_weight)
  134. long current_weight;
  135. long new_weight;
  136. /* add a new weight to the existing one */
  137. {
  138.   /* this should be smarter than this, like doing the log or something */
  139.   if(127 < (current_weight + new_weight)){
  140.     /* the max char.  should be 255, but does not work on all compilers */
  141.     return(127);
  142.   }
  143.   else{
  144.     return(current_weight + new_weight);
  145.   }
  146. }
  147.  
  148. long write_bytes_to_memory(value,size,ptr)
  149. long value;
  150. long size;
  151. unsigned char* ptr;
  152. {
  153.   /* writes the number into memory lsb first.  
  154.      returns the number of bytes written */
  155.   long i;
  156.   long original_value = value;
  157.  
  158.   if(size < 0) /* paranoia */
  159.     panic("attempting to write a negative number of bytes");
  160.  
  161.   ptr += size; /* start at the end of the block and write backwards */
  162.   for (i = 0; i < size; i++){
  163.     ptr--;
  164.     *ptr = (unsigned char)(value & 0xFF);
  165.     value = value >> 8;
  166.   }
  167.   if(value != 0)
  168.     panic("In a call to write_bytes_to_memory, the value %ld can not be represented in %ld bytes", original_value, size);
  169.  
  170.   return(size);
  171. }
  172.         
  173. #endif /* def NOTUSED */
  174.  
  175. /* adds a word to the hashtable. 
  176.  * Returns the 0 if successful. See irext.h for more documentation.
  177.  */
  178. long add_word(word, char_pos, line_pos,
  179.           weight, doc_id, date, word_pair, db, word_position)
  180.      char *word;    /* the word to be indexed, this could be a
  181.                word pair. If NULL there are no more words
  182.                to be indexed */
  183.      long char_pos;    /* the position of the start of the
  184.                word */
  185.      long line_pos;    /* this is passed for the best
  186.                section calculation */
  187.      long weight;    /* how important the word looks
  188.                syntactically (such as is it bold)
  189.                NOT used by signature system */
  190.      long doc_id;     /* current document, this will never be 0 */
  191.      time_t date; /* display day of this document, 0 if not known */
  192.      long word_pair;
  193.      database* db; /* database to insert the document */
  194.      boolean word_position; /* ignored here. */
  195. {
  196.   /* look up the word in the hashtable */
  197.   /* creates it if necessary */    
  198.   hash_entry* wrd_entry;
  199.   hashtable * the_word_memory_hashtable = db->the_word_memory_hashtable;
  200.   /* printf("Word: '%s' doc_id: %ld, pos: %ld, weight: %ld\n",
  201.      word, doc_id, char_pos, weight); */
  202.   
  203.   if(NULL == db->the_word_memory_hashtable){
  204.     panic("The memory word hashtable is not defined.");
  205.   }
  206.  
  207.   /* if we have indexed enough words flush the memory copies to disk.
  208.   if(db->number_of_words_in_hashtable == db->flush_after_n_words)
  209.     flush_memory_hashtable_to_disk(db, false);
  210.     ** not done on sig system **
  211.  */
  212.   
  213.   wrd_entry = look_up_word(word, the_word_memory_hashtable);
  214.   wrd_entry->number_of_occurances ++;
  215.  
  216.   /* check if we have too many of this word before we add it */
  217. #undef MAX_OCCURANCES
  218. #define MAX_OCCURANCES 0x10000000
  219.   if(wrd_entry->number_of_occurances < MAX_OCCURANCES){
  220.     db->number_of_words_in_hashtable ++;
  221.     sig_add_word(word, char_pos, line_pos, weight, doc_id, date, word_pair);
  222.   }
  223.   return(0L);
  224. }
  225.  
  226. void add_stop_words(the_word_memory_hashtable)
  227. hashtable *the_word_memory_hashtable;
  228.      /* add the stop words to the hashtable.  this must be done before
  229.     adding other words */
  230. {
  231.   init_stop_list();
  232.   while(true){
  233.     char *word = next_stop_word();
  234.     hash_entry* wrd_entry;
  235.  
  236.     if(NULL == word)
  237.       break;
  238.     wrd_entry = look_up_word(word, the_word_memory_hashtable);
  239.     wrd_entry->number_of_occurances = STOP_WORD_FLAG;
  240.   }
  241. }
  242.  
  243.  
  244. long finished_add_word(db)
  245. database *db;
  246. {
  247.   /* write out the dictioanry */
  248.   long i;
  249.   long num_words;
  250.  
  251.   db->number_of_words = hashtable_count(db->the_word_memory_hashtable);
  252.   init_dict_file_for_writing(db);
  253.   /* analyze_hashtable_distribution(db->the_word_memory_hashtable); */
  254.   sort_hashtable(db->the_word_memory_hashtable);
  255.   /* exclude the last word which is DICTIONARY_TOTAL_SIZE_WORD */
  256.   num_words = hashtable_count(db->the_word_memory_hashtable);
  257.   if ( 0 == strcmp(db->the_word_memory_hashtable->contents[num_words-1].key,
  258.                    DICTIONARY_TOTAL_SIZE_WORD) ) 
  259.     num_words--;
  260.    
  261.   for(i = 0; i < num_words; i++){
  262.     hash_entry * entry = &db->the_word_memory_hashtable->contents[i];
  263.     if(0 == (STOP_WORD_FLAG & entry->number_of_occurances)){
  264.       /* write out the dictionary entry */
  265.       /* printf("Adding word: %s %ld entries\n", entry->word, entry->number_of_occurances); */
  266.       /* the position in this world is a unique id for every word */
  267.       add_word_to_dictionary(entry->key, i,
  268.                  entry->number_of_occurances, db);
  269.     }
  270.   }
  271.   finished_add_word_to_dictionary(db);
  272.   return(sig_finished_add_word(db));
  273. }
  274.  
  275. /* Add the dictionary to the hastable */
  276.  
  277. void add_dictionary_to_hashtable(db)
  278. database *db;
  279. {
  280.   /* prints the contents of a dictionary */
  281.   FILE *stream = db->dictionary_stream;
  282.   long i, j, new_number_of_dictionary_blocks;
  283.   extern unsigned char *dictionary_header_block, *dictionary_block;
  284.   extern long number_of_dictionary_blocks;
  285.  
  286.   if(stream != NULL) {
  287.     waislog(WLOG_LOW, WLOG_INFO, "Adding dictionary to hastable");
  288.  
  289.     s_fseek(stream, 0L, SEEK_SET);
  290.     new_number_of_dictionary_blocks = read_bytes(DICTIONARY_HEADER_SIZE, stream);
  291.     if(new_number_of_dictionary_blocks > number_of_dictionary_blocks)
  292.       dictionary_header_block = NULL;
  293.     number_of_dictionary_blocks = new_number_of_dictionary_blocks;
  294.     if(NULL == (dictionary_header_block =
  295.         read_dictionary_block(dictionary_header_block,
  296.                       DICTIONARY_HEADER_SIZE,
  297.                       number_of_dictionary_blocks,
  298.                       stream))) {    
  299.       waislog(WLOG_MEDIUM, WLOG_WARNING,
  300.           "Could not read dictionary header block");
  301.       return;
  302.     }
  303.     for(i = 0; i < number_of_dictionary_blocks; i++){
  304.       long pos = dictionary_block_position(i, dictionary_header_block);
  305.       if(NULL == (dictionary_block =
  306.           read_dictionary_block(dictionary_block,
  307.                     pos, DICTIONARY_BLOCK_SIZE, stream))) {
  308.     waislog(WLOG_MEDIUM, WLOG_WARNING,
  309.         "Could not read dictionary block %ld", pos);
  310.       }
  311.       else
  312.     /* iterate over words */
  313.     for(j = 0; j < DICTIONARY_BLOCK_SIZE; j++) {
  314.       char *word = dictionary_block_word(j, dictionary_block);
  315.       hash_entry* wrd_entry;
  316.  
  317.       if(word[0] == '\0' )
  318.         break;
  319.       wrd_entry = look_up_word(word, db->the_word_memory_hashtable);
  320.       wrd_entry->number_of_occurances = 
  321.         dictionary_block_word_occurances(j, dictionary_block);
  322.     }
  323.     }
  324.   }
  325. }
  326.  
  327. long init_add_word(db, hashtable_size, flush_after_n_words)
  328.      database *db;
  329.      long hashtable_size;
  330.      long flush_after_n_words;
  331. {
  332.   if(NULL != db->the_word_memory_hashtable)
  333.     free_hashtable(db->the_word_memory_hashtable);
  334.   db->the_word_memory_hashtable =
  335.     make_hashtable(0, hashtable_size, sizeof(hash_entry));
  336.   db->flush_after_n_words = 0x7FFFFFFF;  /* a large number */
  337.   sig_init_add_word(db, BATCH_UPDATE, ADD_UPDATE);
  338.   add_dictionary_to_hashtable(db);
  339.   add_stop_words(db->the_word_memory_hashtable);
  340.   return(0);
  341. }
  342.